iT邦幫忙

2022 iThome 鐵人賽

DAY 25
0
Modern Web

擁抱 .Net Core系列 第 25

[Day25] 驗證 - Authentication - 2

  • 分享至 

  • xImage
  •  

昨天介紹了Claim以及Identity還有Principal 等驗證中有關身分(你是誰)的物件
今天來看看驗證身分的物件

AuthenticationTicket

實際上在通過門禁所需要的門禁卡不是ClaimPrincipal
而是AuthencationTicket物件
他封裝了ClaimPrincipal以及驗證相關的上下文放在AuthenticationProperties
裡面包含驗證有效時間,過期時間,過期之後要重新導向的位置等資訊
還有一個能自訂所需資訊的Dictionary

AuthenticationTicket.cs

public class AuthenticationTicket
{
    public string AuthenticationScheme { get; }
    public ClaimsPrincipal Principal { get; }
    public AuthenticationProperties Properties { get; }
}

AuthenticationScheme 指的是要如何驗證通關文件的方式,像是basic驗證,cookie驗證,jwt驗證等等

IAuthenticationHandler

IAuthenticationHandler.cs

public interface IAuthenticationHandler
{
    Task InitializeAsync(AuthenticationScheme scheme, HttpContext context);
    Task<AuthenticateResult> AuthenticateAsync();
    Task ChallengeAsync(AuthenticationProperties? properties);
    Task ForbidAsync(AuthenticationProperties? properties);
}
  • AuthenticateAsync: 定義了要如何驗證的方法,並回傳驗證結果(AuthenticateResult)
  • InitializeAsync: 初始化工作,以CookieAuthenticationHandler,會對Reponse的Header添加cookie
  • ChallengeAsync: 當使用者沒有攜帶通關文件的時候或根本不認識的門卡時,就會受到ChallengeAsync
    (沒帶有效的門禁卡就會被櫃檯的小姐姐給攔下來,並請你提供門禁卡)。通常回傳HttpCode:401 unauthorized的錯誤
  • ForbidAsync: 當你有帶門禁卡,櫃台小姐也認識他,但你的權限不夠時,就會被拒絕進入,
    通常回傳HttpCode: 403 Frobidden的錯誤

AuthenticateResult

封裝了驗證結果的物件,包含有效的

  • 通關文件(AuthenticationTicket)
  • 身分(ClaimPrincipal)
  • 跟驗證資訊(AuthenticationProperties)
    還有驗證結果 AuthenticateResult

IAuthenticationSignOutHandler

定義登出方法的介面

public interface IAuthenticationSignOutHandler : IAuthenticationHandler
{
    Task SignOutAsync(AuthenticationProperties? properties);
}

IAuthenticationSignInHandler

定義登入方法的介面

public interface IAuthenticationSignInHandler : IAuthenticationSignOutHandler
{

    Task SignInAsync(ClaimsPrincipal user, AuthenticationProperties? properties);
}

繼承自IAuthenticationSignOutHandler
我還滿喜歡這個想法的
有登入就要記得登出

在.Net Core中使用驗證

UseAuthentication

處理驗證主要透過AuthenticationMiddleware
透過app.UseAuthentication() 在pipeline中加入

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();
// Configure the HTTP request pipeline.
app.UseHttpsRedirection();
app.UseAuthorization();
app.UseRouting();
app.UseAuthentication();
app.MapControllers();
await app.RunAsync();

AuthenticationMiddleware

AuthenticationMiddleware.cs

public IAuthenticationSchemeProvider Schemes { get; set; }

public async Task Invoke(HttpContext context)
{
    context.Features.Set<IAuthenticationFeature>(new AuthenticationFeature
    {
        OriginalPath = context.Request.Path,
        OriginalPathBase = context.Request.PathBase
    });

    var handlers = context.RequestServices.GetRequiredService<IAuthenticationHandlerProvider>();
    foreach (var scheme in await Schemes.GetRequestHandlerSchemesAsync())
    {
        var handler = await handlers.GetHandlerAsync(context, scheme.Name) as IAuthenticationRequestHandler;
        if (handler != null && await handler.HandleRequestAsync())
        {
            return;
        }
    }

    var defaultAuthenticate = await Schemes.GetDefaultAuthenticateSchemeAsync();
    if (defaultAuthenticate != null)
    {
        var result = await context.AuthenticateAsync(defaultAuthenticate.Name);
        if (result?.Principal != null)
        {
            context.User = result.Principal;
        }
        if (result?.Succeeded ?? false)
        {
            var authFeatures = new AuthenticationFeatures(result);
            context.Features.Set<IHttpAuthenticationFeature>(authFeatures);
            context.Features.Set<IAuthenticateResultFeature>(authFeatures);
        }
    }

    await _next(context);
}

首先會把原始路徑設定Feature,未登入時如果被轉導到登入頁面還回的來
接著會從DI Container中取出所有的IAuthenticationHandlerProvider
然後根據所有有註冊的IAuthenticationSchemeProvider 去取有沒有符合的IAuthenticationRequestHandler
若沒有定義該物件,則會使用預設的驗證方式,在驗證通過之後,會把使用者的身分記錄在HttpContext.User

IAuthenticationRequestHandler

IAuthenticationRequestHandler.cs

public interface IAuthenticationRequestHandler : IAuthenticationHandler
{
    Task<bool> HandleRequestAsync();
}

HandleRequestAsync() 方法會決定這個Request有沒有必要往後走,如果值回傳true代表請求須被中斷。

IAuthenticationSchemeProvider

後面還有一些內容,頭痛改天補 => TODO


上一篇
[Day24] 驗證 - Authencation
下一篇
[Day26] 驗證 Authentication - 3
系列文
擁抱 .Net Core30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言